import {
  Material,
  Color
} from '@cesiumjs';
import {
  G3xObjBase
} from "@g3xObjBase"
import {
  g3x_defineProperty,
  g3x_defineReadonly,
  track,
  bind
} from "@g3x/utils";
import {
  autorun,
  reaction,
  intercept,
  extendObservable,
  computed
} from 'mobx';

import uniquePositions from "../uniquePositions"

/* 20 */

class G3xPolyline  extends G3xObjBase{
  constructor(viewer, options) {
    super(options);
    
    viewer && g3x_defineReadonly(this, "viewer", viewer);

    const _this = this;

    _this._pointsColor = [1, 1, 0, 0.95];

    // _this.material.XbsjColorMaterial = new Color();
    // _this.material.XbsjPolylineDashMaterial = new PolylineDash();
    // _this.material.XbsjPolylineArrowMaterial = new PolylineArrow();
    // _this.material.XbsjODLineMaterial = new XbsjODLine();
    // _this.material.XbsjPolylineGlowMaterial = new PolylineGlow();
    // _this.material.XbsjPolylineOutlineMaterial = new PolylineOutline();

    // _XbsjBase8.default.registerProperty(_this, 'material', Polyline.defaultOptions.material);
    // _XbsjBase8.default.registerProperty(_this.material, 'XbsjColorMaterial');
    // _XbsjBase8.default.registerProperty(_this.material, 'XbsjPolylineDashMaterial');
    // _XbsjBase8.default.registerProperty(_this.material, 'XbsjPolylineArrowMaterial');
    // _XbsjBase8.default.registerProperty(_this.material, 'XbsjODLineMaterial');
    // _XbsjBase8.default.registerProperty(_this.material, 'XbsjPolylineGlowMaterial');
    // _XbsjBase8.default.registerProperty(_this.material, 'XbsjPolylineOutlineMaterial');

    _this._primitive = undefined;
    _this.disposers.push(function() {
      return _this._primitive && viewer.scene.primitives.remove(_this._primitive);
    });

    _this._groundPrimitive = undefined;
    _this.disposers.push(function() {
      return _this._groundPrimitive && viewer.scene.groundPrimitives.remove(_this._groundPrimitive);
    });

    _this._boundingSphere = undefined;
    _this.disposers.push(bind(_this, 'enabled', _this, 'show'));

    var arcTypeMap = {
      GEODESIC: Cesium.ArcType.GEODESIC,
      NONE: Cesium.ArcType.NONE,
      RHUMB: Cesium.ArcType.RHUMB
    };

    {
      function createPrimitive() {
        var positions = uniquePositions(_this.positions);
        if (positions.length <= 1) {
          return undefined;
        }
        var cartesians = positions.map(function(p) {
          var _Cesium$Cartesian = Cesium.Cartesian3;
          return _Cesium$Cartesian.fromRadians.apply(_Cesium$Cartesian, p);
        });

        if (_this.loop && positions.length >= 3) {
          cartesians.push(cartesians[0]);
          // 如果只首尾相连，导致的问题时width比较大时，首位相连的线段会有一个小缝
          cartesians.push(cartesians[1]);
        }
        var czmMaterial = _this.material[_this.material.type].material;

        var appearance = new Cesium.PolylineMaterialAppearance({
          material: czmMaterial,
          renderState: {
            depthTest: {
              enabled: _this.depthTest
              // depthMask: this.depthMask, 设置无效，Appearance内部会强行设置
            }
            // translucent: this.forceTranslucent, // 这里的设置同样无效，因为material强制控制是否透明
          }
        });
        appearance.renderState.depthMask = false;

        var primitive = new Cesium.Primitive({
          geometryInstances: new Cesium.GeometryInstance({
            geometry: new Cesium.PolylineGeometry({
              positions: cartesians,
              width: _this.width,
              vertexFormat: Cesium.PolylineMaterialAppearance.VERTEX_FORMAT,
              // arcType: Cesium.ArcType.RHUMB, // 会导致z轴忽隐忽现
              arcType: arcTypeMap[_this.arcType]
            }),
            id: _this
          }),
          appearance: appearance,
          asynchronous: false, // 防止闪烁
          allowPicking: _this.allowPicking, // 不允许拾取
          compressVertices: false // 提升效率
        });

        var ou = primitive.update;
        var that = _this;
        primitive.update = function(frameState) {
          ou.call(this, frameState);
          this._colorCommands.forEach(function(e) {
            // e.pass = Cesium.Pass.OVERLAY;
            that.forcePass && (e.pass = that.forcePass);
          });
        };

        return primitive;
      };

      var createGroundPrimitive = function createGroundPrimitive() {
        var positions = (0, _uniquePositions2.default)(_this.positions);
        if (positions.length <= 1) {
          return undefined;
        }
        var cartesians = positions.map(function(p) {
          var _Cesium$Cartesian2;

          return (_Cesium$Cartesian2 = Cesium.Cartesian3).fromRadians.apply(_Cesium$Cartesian2, (0,
            _toConsumableArray3.default)(p));
        });

        if (_this.loop && positions.length >= 3) {
          cartesians.push(cartesians[0]);
          // 如果只首尾相连，导致的问题时width比较大时，首位相连的线段会有一个小缝
          cartesians.push(cartesians[1]);
        }
        var czmMaterial = _this.material[_this.material.type].material;

        var groundPrimitive = new Cesium.GroundPolylinePrimitive({
          geometryInstances: new Cesium.GeometryInstance({
            geometry: new Cesium.GroundPolylineGeometry({
              positions: cartesians,
              width: _this.width,
              vertexFormat: Cesium.PolylineMaterialAppearance.VERTEX_FORMAT,
              // arcType: Cesium.ArcType.RHUMB, // 会导致z轴忽隐忽现
              arcType: arcTypeMap[_this.arcType]
            }),
            id: _this
          }),
          appearance: new Cesium.PolylineMaterialAppearance({
            material: czmMaterial,
            renderState: {
              depthTest: {
                enabled: _this.depthTest
                // depthMask: this.depthMask,
              }
              // translucent: this.forceTranslucent, // 这里的设置同样无效，因为material强制控制是否透明
            }
          }),
          asynchronous: false, // 防止闪烁
          allowPicking: _this.allowPicking, // 不允许拾取
          compressVertices: false // 提升效率
        });

        return groundPrimitive;
      };

      var createPolyline = function createPolyline() {
        var positions = _this.positions;
        _this._primitive && _this._earth.czm.scene.primitives.remove(_this._primitive);
        _this._primitive = undefined;
        _this._groundPrimitive && _this._earth.czm.scene.groundPrimitives.remove(_this._groundPrimitive);
        _this._groundPrimitive = undefined;

        if (positions.length >= 2) {
          if (!_this.ground) {
            _this._primitive = createPrimitive();
            _this._primitive && _this._earth.czm.scene.primitives.add(_this._primitive);
          } else {
            _this._groundPrimitive = createGroundPrimitive();
            _this._groundPrimitive && _this._earth.czm.scene.groundPrimitives.add(_this
              ._groundPrimitive);
          }
        }
      };

      var updatePolyline = function updatePolyline() {
        var show = _this.show;
        _this._primitive && (_this._primitive.show = show);
        _this._groundPrimitive && (_this._groundPrimitive.show = show);

        var czmMaterial = _this.material[_this.material.type].material;
        _this._primitive && (_this._primitive.appearance.material = czmMaterial);
        _this._groundPrimitive && (_this._groundPrimitive.appearance.material = czmMaterial);
      };

      var updateBoundingSphere = function updateBoundingSphere() {
        var positions = _this.positions;
        var cartesians = positions.map(function(p) {
          var _Cesium$Cartesian3;

          return (_Cesium$Cartesian3 = Cesium.Cartesian3).fromRadians.apply(_Cesium$Cartesian3, (0,
            _toConsumableArray3.default)(p));
        });
        _this._boundingSphere = Cesium.BoundingSphere.fromPoints(cartesians, _this._boundingSphere);
      };

      _this.disposers.push((0, _mobx.reaction)(function() {
        return {
          positions: [].concat((0, _toConsumableArray3.default)(_this.positions.map(function(e) {
            return [].concat((0, _toConsumableArray3.default)(e));
          }))),
          loop: _this.loop,
          ground: _this.ground,
          depthTest: _this.depthTest,
          // depthMask: this.depthMask,
          // forceTranslucent: this.forceTranslucent,
          arcType: _this.arcType,
          width: _this.width,
          allowPicking: _this.allowPicking
        };
      }, function() {
        createPolyline();
        updateBoundingSphere();
        updatePolyline();
      }));

      _this.disposers.push((0, _mobx.autorun)(updatePolyline));
    }
  }
}

var Polyline = function(_XbsjCzmObj) {
  (0, _inherits3.default)(Polyline, _XbsjCzmObj);

  function Polyline(earth, guid) {

    {
      var createPrimitive = function createPrimitive() {
        var positions = (0, _uniquePositions2.default)(_this.positions);
        if (positions.length <= 1) {
          return undefined;
        }
        var cartesians = positions.map(function(p) {
          var _Cesium$Cartesian;

          return (_Cesium$Cartesian = Cesium.Cartesian3).fromRadians.apply(_Cesium$Cartesian, (0,
            _toConsumableArray3.default)(p));
        });

        if (_this.loop && positions.length >= 3) {
          cartesians.push(cartesians[0]);
          // 如果只首尾相连，导致的问题时width比较大时，首位相连的线段会有一个小缝
          cartesians.push(cartesians[1]);
        }
        var czmMaterial = _this.material[_this.material.type].material;

        var appearance = new Cesium.PolylineMaterialAppearance({
          material: czmMaterial,
          renderState: {
            depthTest: {
              enabled: _this.depthTest
              // depthMask: this.depthMask, 设置无效，Appearance内部会强行设置
            }
            // translucent: this.forceTranslucent, // 这里的设置同样无效，因为material强制控制是否透明
          }
        });
        appearance.renderState.depthMask = false;

        var primitive = new Cesium.Primitive({
          geometryInstances: new Cesium.GeometryInstance({
            geometry: new Cesium.PolylineGeometry({
              positions: cartesians,
              width: _this.width,
              vertexFormat: Cesium.PolylineMaterialAppearance.VERTEX_FORMAT,
              // arcType: Cesium.ArcType.RHUMB, // 会导致z轴忽隐忽现
              arcType: arcTypeMap[_this.arcType]
            }),
            id: _this
          }),
          appearance: appearance,
          asynchronous: false, // 防止闪烁
          allowPicking: _this.allowPicking, // 不允许拾取
          compressVertices: false // 提升效率
        });

        var ou = primitive.update;
        var that = _this;
        primitive.update = function(frameState) {
          ou.call(this, frameState);
          this._colorCommands.forEach(function(e) {
            // e.pass = Cesium.Pass.OVERLAY;
            that.forcePass && (e.pass = that.forcePass);
          });
        };

        return primitive;
      };

      var createGroundPrimitive = function createGroundPrimitive() {
        var positions = (0, _uniquePositions2.default)(_this.positions);
        if (positions.length <= 1) {
          return undefined;
        }
        var cartesians = positions.map(function(p) {
          var _Cesium$Cartesian2;

          return (_Cesium$Cartesian2 = Cesium.Cartesian3).fromRadians.apply(_Cesium$Cartesian2, (0,
            _toConsumableArray3.default)(p));
        });

        if (_this.loop && positions.length >= 3) {
          cartesians.push(cartesians[0]);
          // 如果只首尾相连，导致的问题时width比较大时，首位相连的线段会有一个小缝
          cartesians.push(cartesians[1]);
        }
        var czmMaterial = _this.material[_this.material.type].material;

        var groundPrimitive = new Cesium.GroundPolylinePrimitive({
          geometryInstances: new Cesium.GeometryInstance({
            geometry: new Cesium.GroundPolylineGeometry({
              positions: cartesians,
              width: _this.width,
              vertexFormat: Cesium.PolylineMaterialAppearance.VERTEX_FORMAT,
              // arcType: Cesium.ArcType.RHUMB, // 会导致z轴忽隐忽现
              arcType: arcTypeMap[_this.arcType]
            }),
            id: _this
          }),
          appearance: new Cesium.PolylineMaterialAppearance({
            material: czmMaterial,
            renderState: {
              depthTest: {
                enabled: _this.depthTest
                // depthMask: this.depthMask,
              }
              // translucent: this.forceTranslucent, // 这里的设置同样无效，因为material强制控制是否透明
            }
          }),
          asynchronous: false, // 防止闪烁
          allowPicking: _this.allowPicking, // 不允许拾取
          compressVertices: false // 提升效率
        });

        return groundPrimitive;
      };

      var createPolyline = function createPolyline() {
        var positions = _this.positions;
        _this._primitive && _this._earth.czm.scene.primitives.remove(_this._primitive);
        _this._primitive = undefined;
        _this._groundPrimitive && _this._earth.czm.scene.groundPrimitives.remove(_this._groundPrimitive);
        _this._groundPrimitive = undefined;

        if (positions.length >= 2) {
          if (!_this.ground) {
            _this._primitive = createPrimitive();
            _this._primitive && _this._earth.czm.scene.primitives.add(_this._primitive);
          } else {
            _this._groundPrimitive = createGroundPrimitive();
            _this._groundPrimitive && _this._earth.czm.scene.groundPrimitives.add(_this
              ._groundPrimitive);
          }
        }
      };

      var updatePolyline = function updatePolyline() {
        var show = _this.show;
        _this._primitive && (_this._primitive.show = show);
        _this._groundPrimitive && (_this._groundPrimitive.show = show);

        var czmMaterial = _this.material[_this.material.type].material;
        _this._primitive && (_this._primitive.appearance.material = czmMaterial);
        _this._groundPrimitive && (_this._groundPrimitive.appearance.material = czmMaterial);
      };

      var updateBoundingSphere = function updateBoundingSphere() {
        var positions = _this.positions;
        var cartesians = positions.map(function(p) {
          var _Cesium$Cartesian3;

          return (_Cesium$Cartesian3 = Cesium.Cartesian3).fromRadians.apply(_Cesium$Cartesian3, (0,
            _toConsumableArray3.default)(p));
        });
        _this._boundingSphere = Cesium.BoundingSphere.fromPoints(cartesians, _this._boundingSphere);
      };

      _this.disposers.push((0, _mobx.reaction)(function() {
        return {
          positions: [].concat((0, _toConsumableArray3.default)(_this.positions.map(function(e) {
            return [].concat((0, _toConsumableArray3.default)(e));
          }))),
          loop: _this.loop,
          ground: _this.ground,
          depthTest: _this.depthTest,
          // depthMask: this.depthMask,
          // forceTranslucent: this.forceTranslucent,
          arcType: _this.arcType,
          width: _this.width,
          allowPicking: _this.allowPicking
        };
      }, function() {
        createPolyline();
        updateBoundingSphere();
        updatePolyline();
      }));

      _this.disposers.push((0, _mobx.autorun)(updatePolyline));
    }

    _this._points = new _Points2.default(earth);
    _this.disposers.push(function() {
      return _this._points = _this._points && _this._points.destroy();
    });

    _this.disposers.push((0, _mobx.reaction)(function() {
      return _this.positions.map(function(p) {
        return [].concat((0, _toConsumableArray3.default)(p));
      });
    }, function(positions) {
      var diffLen = positions.length - _this._points.points.length;
      if (diffLen > 0) {
        for (var i = 0; i < diffLen; ++i) {
          _this._points.points.push({
            color: [].concat((0, _toConsumableArray3.default)(_this._pointsColor))
          });
        }
      } else if (diffLen < 0) {
        for (var _i = 0; _i < -diffLen; ++_i) {
          var _this$_points$points;

          _this._points.points[positions.length + _i].show = false;
          (_this$_points$points = _this._points.points[positions.length + _i].color).splice.apply(
            _this$_points$points, [0, 4].concat((0, _toConsumableArray3.default)(_this
              ._pointsColor)));
        }
      }

      positions.forEach(function(value, index) {
        var _this$_points$points2;

        _this._points.points[index].show = _this.enabled;
        (_this$_points$points2 = _this._points.points[index].position).splice.apply(
          _this$_points$points2, [0, 3].concat((0, _toConsumableArray3.default)(value)));
      });
    }, {
      fireImmediately: true
    }));

    _this.disposers.push((0, _mobx.reaction)(function() {
      return _this.show && _this.showHelper || _this.isSelected;
    }, function(show) {
      _this._points.show = show;
    }, {
      fireImmediately: true
    }));

    _this.disposers.push((0, _registerInteractionProperty.registerPolylineCreating)(_this._earth, _this, {
      polylineCreatingProperty: 'creating'
    }));

    _this.disposers.push((0, _registerInteractionProperty.registerPolylineEditing)(_this._earth, _this, {
      polylineEditingProperty: 'editing'
    }));
    return _this;
  }

  (0, _createClass3.default)(Polyline, [{
    key: 'flyTo',
    value: function flyTo() {
      var camera = this._earth.czm.scene.camera;
      camera.flyToBoundingSphere(this._boundingSphere);
    }

    // 暂不增加isSelected的联动
    // onclick() {
    //     this.isSelected = true;
    // }

    // onclickout() {
    //     this.isSelected = false;
    // }

  }, {
    key: 'destroy',
    value: function destroy() {
      return (0, _get3.default)(Polyline.prototype.__proto__ || (0, _getPrototypeOf2.default)(Polyline
        .prototype), 'destroy', this).call(this);
    }
  }, {
    key: 'boundingSphere',
    get: function get() {
      return this._boundingSphere;
    }
  }]);
  return Polyline;
}(_XbsjCzmObj3.default);

Polyline.defaultOptions = {
  positions: [],
  show: true,
  showHelper: false,
  width: 2,
  depthTest: false,
  // depthMask: false, // Appearance.getRenderState()函数会根据translucent来强制修改depthMask属性，透明的就强制不写深度，所以不能直接设置renderState
  // forceTranslucent: false, // 强制设置是否透明，如果强制透明，则depthMask为false
  forcePass: undefined,
  arcType: 'GEODESIC', // GEODESIC 地表最近距离插值 NONE 直线，不插值 RHUMB 保持地理方向一致的插值
  loop: false,
  material: {
    type: 'XbsjColorMaterial',
    XbsjColorMaterial: {},
    XbsjPolylineDashMaterial: {},
    XbsjPolylineArrowMaterial: {},
    XbsjODLineMaterial: {},
    XbsjPolylineGlowMaterial: {},
    XbsjPolylineOutlineMaterial: {}
  },
  ground: false
};

var xbsjSchema = {
  title: "Polyline Property",
  type: "object",
  properties: {
    /**
     * 位置数组，形式如 [[2.012, 0.65, 10], [1.9, 0.7, 20], ...] 每一个元素分别表示 经度、纬度、高度，其中经度纬度以弧度为单位，高度以米为单位
     * @type {array}
     * @instance
     * @default true
     * @memberof Obj.Polyline
     */
    positions: {
      type: 'array',
      title: '位置数组',
      default: [],
      description: '位置数组'
    },
    /**
     * 是否在三维窗口中显示
     * @type {boolean}
     * @instance
     * @default true
     * @memberof Obj.Polyline
     */
    show: {
      type: 'boolean',
      title: '是否在三维窗口中显示',
      default: true,
      description: '是否在三维窗口中显示'
    },
    /**
     * 是否显示辅助线框
     * @type {boolean}
     * @instance
     * @default false
     * @memberof Obj.Polyline
     */
    showHelper: {
      type: 'boolean',
      title: '是否显示辅助线框',
      default: false,
      description: '是否显示辅助线框'
    },
    /**
     * 线宽，单位像素
     * @type {number}
     * @instance
     * @default 2.0
     * @memberof Obj.Polygon
     */
    width: {
      type: 'number',
      title: '线宽，单位像素',
      default: 2.0,
      description: '线宽，单位像素'
    },
    /**
     * 是否开启深度检测
     * @type {boolean}
     * @instance
     * @default false
     * @memberof Obj.Polyline
     */
    depthTest: {
      type: 'boolean',
      title: '是否开启深度检测',
      default: false,
      description: '是否开启深度检测'
    },
    /**
     * 强制修改渲染顺序
     * 目前Cesium的渲染顺序有： <br/>
     *  ENVIRONMENT : 0, <br/>
     *  COMPUTE : 1, <br/>
     *  GLOBE : 2, <br/>
     *  TERRAIN_CLASSIFICATION : 3, <br/>
     *  CESIUM_3D_TILE : 4, <br/>
     *  CESIUM_3D_TILE_CLASSIFICATION : 5, <br/>
     *  CESIUM_3D_TILE_CLASSIFICATION_IGNORE_SHOW : 6, <br/>
     *  OPAQUE : 7, <br/>
     *  TRANSLUCENT : 8, <br/>
     *  OVERLAY : 9, <br/>
     *  NUMBER_OF_PASSES : 10 <br/>
     * @type {number|undefined}
     * @instance
     * @default undefined
     * @memberof Obj.Polyline
     */
    forcePass: {
      type: ['number', 'undefined'],
      title: '是否开启深度检测',
      default: undefined,
      description: '是否开启深度检测'
    },
    /**
     * 弧线样式，因为地球是圆形的，两点之间不能走直线，需要确定这个弧线该如何走 <br/>
     * 弧线样式有3种： <br/>
     * GEODESIC 地表最近距离插值 <br/>
     * NONE 直线，不插值 <br/>
     * RHUMB 保持地理方向一致的插值 <br/>
     * @type {string}
     * @instance
     * @default 'GEODESIC'
     * @memberof Obj.Polyline
     */
    arcType: {
      type: 'string',
      title: '弧线样式',
      default: 'GEODESIC',
      description: '弧线样式'
    },
    /**
     * 折线材质设置
     * @type {object}
     * @property {string} - 类型，可以是Color/PolylineDash/PolylineArrow/PolylineGlow/PolylineOutline/XbsjODLine
     * @property {Obj.Polyline.Material.Color}  - 纯颜色材质
     * @property {Obj.Polyline.Material.PolylineDash} - 点画线材质
     * @property {Obj.Polyline.Material.PolylineArrow} - 箭头材质
     * @property {Obj.Polyline.Material.PolylineGlow} - 发光材质
     * @property {Obj.Polyline.Material.PolylineOutline} - 外轮廓线材质
     * @property {Obj.Polyline.Material.XbsjODLine} - OD线材质
     * @instance
     * @memberof Obj.Polyline
     */
    material: {},
    /**
     * 是否首尾相连
     * @type {boolean}
     * @instance
     * @default false
     * @memberof Obj.Polyline
     */
    loop: {
      type: 'boolean',
      title: '是否首尾相连',
      default: false,
      description: '是否首尾相连'
    },
    /**
     * 是否贴地
     * @type {boolean}
     * @instance
     * @default true
     * @memberof Obj.Polyline
     */
    ground: {
      type: 'boolean',
      title: '是否贴地',
      default: true,
      description: '是否贴地'
    }
  }
};

Polyline.xbsjSchema = xbsjSchema;

var xbsjClassification = [{
  name: {
    chinese: '通用',
    english: 'General'
  },
  properties: ['positions', 'show', 'showHelper', 'width', 'depthTest', 'forcePass', 'arcType', 'loop',
    'material', 'ground'
  ]
}];

Polyline.xbsjClassification = xbsjClassification;

_XbsjObject2.default.registerType(Polyline, 'Polyline');

exports.default = Polyline;

/***/
})

export default G3xPolyline;
